---@class GT.item
---@field item Item 物品
---@field pos Point 位置
---@field iid ItemKey 物品编号
---@field player Role 所属玩家
---@field binding UnitKeyFloatAttr 绑定值
GT.item = class()

---@class item_data
---@field item Item 物品
---@field pos Point 位置
---@field iid ItemKey 物品编号
---@field player Role 所属玩家


---创建物品
---@param data item_data
function GT.item:ctor(data)
    self.item = data.item

    for k, v in pairs(UnitKeyFloatAttr) do
        self[k] = self:api_get_attr(v)
    end
    self.bind = new(bind, self)
    self.binding = self.bind.bindable
    for k, v in pairs(UnitKeyFloatAttr) do
        self.bind:add_({
            key = k,
            func = function(val, old)
                if val == nil then
                    return
                end
                self[k] = val
                self:set_basic_attributes(v, self[k])
            end
        })
    end
end

---转对象
---@param item Item
---@return GT.item
function GT.item.obj(item)
    if item == nil then
        return nil
    end

    local obj = all_cache:get(tostring(item))
    if obj == nil then
        obj = new(GT.item, { item = item })
        all_cache:set(tostring(item), obj)
    end
    return obj
end

function GT.item:__tostring()
    return tostring(self.item)
end

---创建一个物品
---@param pos GT.point 位置
---@param iid ItemKey 物品key
---@param player GT.player 玩家 可为nil
---@return GT.item
function GT.item.create_items_id(pos, iid, player)
    local p = nil
    if player ~= nil then
        p = player.player
    end
    return GT.item.obj(game_api.create_item_by_id(pos.point, iid, p))
end

--- 按数量 创建物品
---@param pos  GT.point
---@param iid Int32
---@param player GT.player
---@param num Int32
function GT.item:create_items(pos, iid, player, num)
    game_api.create_items(self.pos, num, self.iid, self.player)
end

--- 根据id获取物品
---@param id ItemId 物品ID
---@return GT.item
function GT.item.get_item(id)
    return GT.item.obj(game_api.get_item(id))
end

--- 获取物品编号
---@return ItemKey
function GT.item:get_ItemKey()
    return self.item.api_get_key()
end

--- 设置物品名称
---@param name Str 物品名称
function GT.item:set_name(name)
    self.item.set_name(name)
end

--- 获取物品名称
---@return Str
function GT.item:get_name()
    return self.item.get_name()
end

--- 获取物品配置名称
---@return Str
function GT.item:api_get_conf_name()
    return self.item.api_get_conf_name()
end

--- 设置物品描述
---@param desc Str 物品描述
function GT.item:api_set_desc(desc)
    self.item.api_set_desc(desc)
end

--- 获取物品描述
---@return Str
function GT.item:api_get_desc()
    return self.item.api_get_desc()
end

--- 获取物品配置描述
---@return Str
function GT.item:api_get_conf_desc()
    return self.item.api_get_conf_desc()
end

--- 获取物品类型
---@return UInt32
function GT.item:api_get_type()
    return self.item.api_get_type()
end

--- 获取物品等级
---@return UInt32
function GT.item:api_get_level()
    return self.item.api_get_level()
end

--- 设置物品等级
---@param level UInt32 等级
function GT.item:api_set_level(level)
    self.item.api_set_level(level)
end

--- 丢弃物品
---@param pos FPoint 点
---@param stack_cnt Actor 数量
function GT.item:api_drop_self(pos, stack_cnt)
    self.item.api_drop_self(pos, stack_cnt)
end

--- 移除物品
function GT.item:api_remove()
    self.item.api_remove()
end

--- 设置物品出售
---@param sale_state Bool 可否出售
function GT.item:api_set_sale_state(sale_state)
    self.item.api_set_sale_state(sale_state)
end

--- 设置物品堆叠数
---@param stack_cnt Int32 堆叠数
function GT.item:api_set_stack_cnt(stack_cnt)
    self.item.api_set_stack_cnt(stack_cnt)
end

--- 设置物品充能数
---@param charge_cnt Int32 充能数
function GT.item:api_set_charge_cnt(charge_cnt)
    self.item.api_set_charge_cnt(charge_cnt)
end

--- 设置物品最大充能数
---@param max_charge Int32 最大充能数
function GT.item:api_set_max_charge(max_charge)
    self.item.api_set_max_charge(max_charge)
end

--- 获取物品位置
---@return Point
function GT.item:api_get_position()
    return self.item.api_get_position()
end

--- 物品是否在场景中
---@return Bool
function GT.item:api_is_in_scene()
    return self.item.api_is_in_scene()
end

--- 获取物品堆叠数
---@return UInt32
function GT.item:api_get_stack_cnt()
    return self.item.api_get_stack_cnt()
end

--- 获取物品堆叠类型
---@return UInt32
function GT.item:api_get_stack_type()
    return self.item.api_get_stack_type()
end

--- 获取物品充能数
---@return UInt32
function GT.item:api_get_charge_cnt()
    return self.item.api_get_charge_cnt()
end

--- 获取物品充能数
---@return UInt32
function GT.item:api_get_max_charge()
    return self.item.api_get_max_charge()
end

--- 设置物品丢弃
---@param can_drop Bool 可否丢弃
function GT.item:set_drop(can_drop)
    self.item.api_set_droppable(can_drop)
end

--- 设置物品出售
---@param can_sell Bool 可否丢弃
function GT.item:api_set_sellable(can_sell)
    self.item.api_set_sellable(can_sell)
end

--- 设置物品生命值
---@param hp Float 生命值
function GT.item:api_set_hp(hp)
    self.item.api_set_hp(hp)
end

--- 获取物品丢弃
---@return Bool
function GT.item:api_get_droppable()
    return self.item.api_get_droppable()
end

--- 获取物品出售
---@return Bool
function GT.item:api_get_sellable()
    return self.item.api_get_sellable()
end

--- 获取物品生命值
---@return Fixed
function GT.item:api_get_hp()
    return self.item.api_get_hp()
end

--- 设置物品附加属性
---@param attr_element_field Str 属性名
---@param attr_key Str 属性成分名
---@param val Float 属性值
function GT.item:api_set_attr(attr_element_field, attr_key, val)
    self.item.api_set_attr(attr_element_field, attr_key, val)
end

--- 增加物品附加属性
---@param attr_element_field Str 属性名
---@param attr_key Str 属性成分名
---@param delta Float 属性值
function GT.item:api_change_attr(attr_element_field, attr_key, delta)
    self.item.api_change_attr(attr_element_field, attr_key, delta)
end

--- 获取物品附加属性
---@param attr_element_field Str 属性成分名
---@param attr_key Str 属性名
---@return Float
function GT.item:api_get_attr(attr_element_field, attr_key)
    return self.item.api_get_attr(attr_element_field, attr_key)
end

--- 设置物品所有者
---@param creator Role 所有者
function GT.item:api_set_creator(creator)
    self.item.api_set_creator(creator)
end

--- 获得物品所有者
---@return Role
function GT.item:api_get_creator()
    return self.item.api_get_creator()
end

--- 获得物品拥有者
---@return Unit
function GT.item:api_get_owner()
    return self.item.api_get_owner()
end

--- 添加物品堆叠数
---@param cnt Int32 堆叠数
function GT.item:api_add_stack(cnt)
    self.item.api_add_stack(cnt)
end

--- 添加物品充能数
---@param cnt Int32 充能数
function GT.item:api_add_charge(cnt)
    self.item.api_add_charge(cnt)
end

--- 获取物品缩放
---@return Fixed
function GT.item:api_get_scale()
    return self.item.api_get_scale()
end

--- 获取物品朝向
---@return Fixed
function GT.item:api_get_face_angle()
    return self.item.api_get_face_angle()
end

--- 设置物品缩放
---@param scale Float 缩放
function GT.item:api_set_scale(scale)
    self.item.api_set_scale(scale)
end

--- 设置物品位置
---@param point Point 物品位置
function GT.item:api_set_position(point)
    self.item.api_set_position(point)
end

--- 设置物品朝向
---@param face_angle Float 物品朝向
function GT.item:api_set_face_angle(face_angle)
    self.item.api_set_face_angle(face_angle)
end

--- 是否在区域内
---@param area Area 区域
---@return Bool
function GT.item:api_is_in_area(area)
    return self.item.api_is_in_area(area)
end

--- 移动物品到点
---@param point Point 点
function GT.item:api_transmit(point)
    self.item.api_transmit(point)
end

--- 物品添加标签
---@param tag Str 标签
function GT.item:api_add_tag(tag)
    self.item.api_add_tag(tag)
end

--- 物品删除标签
---@param tag Str 标签
function GT.item:api_remove_tag(tag)
    self.item.api_remove_tag(tag)
end

--- 物品是否拥有标签
---@param tag Str 标签
---@return Bool
function GT.item:api_has_tag(tag)
    return self.item.api_has_tag(tag)
end

--- 物品移除键值对
---@param k Str 要移除的键
function GT.item:api_remove_kv(k)
    self.item.api_remove_kv(k)
end

--- 获取物品在场景中的对应实体
---@return Unit
function GT.item:api_get_item_unit()
    return self.item.api_get_item_unit()
end

--- 获取物品id
---@return number
function GT.item:id()
    return self.item.api_get_id()
end

--- 物品是否在物品栏
---@return Bool
function GT.item:api_is_in_bar()
    return self.item.api_is_in_bar()
end

--- 物品是否在背包栏中
---@return Bool
function GT.item:api_is_in_pkg()
    return self.item.api_is_in_pkg()
end

--- 对物品所属单位的所属玩家关系播放音乐
---@param camp_target RoleRelation 玩家关系
---@param sid AudioKey 乐曲编号
---@param loop Bool 是否循环
function GT.item:api_play_sound_by_item_for_role_relation(camp_target, sid, loop)
    self.item.api_play_sound_by_item_for_role_relation(camp_target, sid, loop)
end

--- 获取物品的主动技能
---@return GT.ability
function GT.item:api_get_positive_ability()
    return GT.ability.obj(self.item.api_get_positive_ability())
end

--- 获取物品的被动技能
---@param index UInt64 索引 0开始
---@return GT.ability
function GT.item:api_get_passive_ability(index)
    return GT.ability.obj(self.item:api_get_passive_ability(index))
end

--- 获取物品的被动技能
---@return GT.ability[]
function GT.item:get_ability()
    ---@type GT.ability[]
    local data = {}
    for i = 1, 10, 1 do
        local a = self:api_get_passive_ability(i - 1)
        if a ~= nil then
            table.insert(data, a)
        end
    end
    return data
end

---物品主动技能文本
function GT.item:set_item_skill_active()
    local as = self:api_get_positive_ability()
    if as ~= nil then
        return as:name() .. "-主动-(CD:" .. as:cd() .. ")-" .. as:desc()
    else
        return ""
    end
end

---物品属性文本
---@param p GT.player
---@param i GT.item
function GT.item:item_attr()
    local sb = StringBuilder.new()
    for k, v in pairs(UnitKeyFloatAttr) do
        local data = self:get_attributes(AttrType['增益'], v)
        if data > 0 then
            if string.findi(k, '%%') ~= nil then
                sb:append_line("#33FF00" .. k .. "+" .. data .. "%" .. "#FFFFFF")
            else
                sb:append_line("#33FF00" .. k .. "+" .. data .. "#FFFFFF")
            end
        end
    end
    return sb:tostring(true)
end

---物品被动技能文本
---@param p GT.player
---@param i GT.item
function GT.item:set_item_skill_passive()
    local as = self:get_ability()
    local sb = StringBuilder.new()
    for k, v in pairs(as) do
        sb:append_line(v:name() .. "-被动-" .. v:desc())
    end
    return sb:tostring(true)
end

---物品Tip
function GT.item:tip()
    local sb = StringBuilder.new()
    sb:append_line(self:item_attr())
    sb:append_line(self:set_item_skill_active())
    sb:append_line(self:set_item_skill_passive())
    return sb:tostring(true)
end

--- 设置物品的图标为图片
---@param icon_id Texture 图标
function GT.item:api_set_item_icon(icon_id)
    self.item.api_set_item_icon(icon_id)
end

--- 获取物品的图标
---@return Texture
function GT.item:api_get_item_icon()
    return self.item.api_get_item_icon()
end

--- 物品所在背包槽位类型
---@return SlotType
function GT.item:api_get_item_slot_type()
    return self.item.api_get_item_slot_type()
end

--- 物品所在的格子位置索引
---@return Int32
function GT.item:api_get_item_slot_idx()
    return self.item.api_get_item_slot_idx()
end

--- 物品实例添加被动技能
---@param ability_id AbilityKey 技能id
---@param ability_level Int32 技能等级
function GT.item:api_item_add_passive_ability(ability_id, ability_level)
    self.item.api_item_add_passive_ability(ability_id, ability_level)
end

--- 返回指定物品类型的名字
---@return Str
function GT.item:get_item_name_by_type()
    return game_api.get_item_name_by_type(self:get_ItemKey())
end

--- 获取物品icon图标的图片id
---@return Int32
function GT.item:get_icon_id_by_item_type()
    return game_api.get_icon_id_by_item_type(self:get_ItemKey())
end

--- 返回指定物品类型的描述
---@return Str
function GT.item:get_item_desc_by_type()
    return game_api.get_item_desc_by_type(self:get_ItemKey())
end

--- 返回指定物品名字的字符串属性值
---@param name Str 属性名
---@return Str
function GT.item:get_item_key_str_attr(name)
    return game_api.get_item_key_str_attr(self:get_ItemKey(), name)
end

--- 获取最近创建的物品
---@return GT.item
function GT.item.get_last_created_item()
    return GT.item.obj(game_api.get_last_created_item())
end

--- 获取物品配置名称
---@param key ItemKey item_id
---@return Str
function GT.item.get_item_conf_name(key)
    return game_api.get_item_conf_name(key)
end

--TODO:这里的key需要在lua层处理
---@param key string 属性key
---@param value number 属性值
---设置增益属性
function GT.item:set_basic_attributes(key, value)
    self.item.api_set_attr(AttrType['增益'], key, Fix32(value))
end

--TODO:这里的key需要在lua层处理
---@param key string 属性key
---@param value number 属性值
---增加基础属性
function GT.item:add_basic_attributes(key, value)
    self.item.api_change_attr("ATTR_BASE", key, Fix32(value))
end

--TODO:这里的key需要在lua层处理
---@param key string 属性key
---获得增益属性
function GT.item:api_get_attr(key)
    return self.item.api_get_attr(AttrType['增益'], key):float()
end




---获取物品的属性
---@param type AttrType
---@param key string 属性key
---@param ratio Bool 是否为比率
function GT.item:get_attributes(type, key)
    if AttrType['基础加成%'] == type or AttrType['增益加成%'] == type or AttrType['总属性加成%'] == type then
        return self.item.api_get_attr(type, key):float()
    end

    return self.item.api_get_attr(type, key):int()
end

---@generic K
---@generic V
---创建自定义值 取值 直接 对象['K'] 修改为 对象.binding['K']
---@param k K
---@param v V
---@param call kv_call
function GT.item:set(k, v, call)
    self[k] = v
    if call==nil then
        return 
    end
    self.bind:add_({
        key = k,
        func = function(val, old)
            if val == nil then
                return
            end
            self[k] = val
            call(k, val, old)
        end
    })
end


---物品-单位获得
---@param fun ADD_ITEM
function GT.item:event_unit_get_items(fun)
    GT.event.ADD_ITEM(function(u, i)
        if i:id() == self:id() then
            fun(u, i)
        end
    end)
end

---物品-单位失去
---@param fun REMOVE_ITEM
function GT.item:event_unit_get_items(fun)
    GT.event.REMOVE_ITEM(function(u, i)
        if i:id() == self:id() then
            fun(u, i)
        end
    end)
end
